package com.gome.spiderkit.client;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.Code;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Context;

import ProcessRouter.MessageStruct.ManagerInfoStruct;

import com.google.protobuf.InvalidProtocolBufferException;

public class GlobalConfig {
	
	private static GlobalConfig instance = new GlobalConfig();;
	
	private String rootPath = "/spider_v2";
    private static final int SESSION_TIME   = 4000;
    
    CuratorFramework zkclient = null;
    
	private Context content = null;
    private String zkhost = "";
    private Map<String, List<String>> groupMap = new HashMap<String, List<String>>();
    
    private GlobalConfig() {
    	content = ZMQ.context(10);
    }
    
    public static GlobalConfig getInstance() {
    	return instance;
    }
    
    public void connect(String zkhost) {
    	RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
    	zkclient = CuratorFrameworkFactory.newClient(zkhost, retryPolicy);
    	zkclient.start();
    }
    
    private List<String> getNodes(String group) throws Exception {
    	String mpath = rootPath + "/" + group;
    	return zkclient.getChildren().watched().forPath(mpath);
    }
    
    public List<String> getGroups() throws Exception {
    	return zkclient.getChildren().watched().forPath(rootPath);
    }
    
    private byte[] getData(String mpath) throws Exception {
    	return zkclient.getData().forPath(mpath);
    }
    
	public void close() {
		if (zkclient != null) {
			zkclient.close();
			zkclient = null;
		}
	}
	
	public Context gZMQCTX() {
		return content;
	}

	public String getProtocolFromGroup(String group, boolean isStatic) {
		String protocol = "";
		String mpath = rootPath + "/" + group;
		List<String> mlist;

		try {
			mlist = getNodes(group);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		
        double score = -1.0;
        boolean first = true;
        double tcurrpc = 0.0;
        double toverflowpc = 0.0;
        double ntoverflowpc = 0.0;
        
        List<ManagerInfoStruct> infos = new ArrayList<ManagerInfoStruct>();
        
		for (String m : mlist) {
			String dpath = mpath + "/" + m + "/stateinfo";
			ManagerInfoStruct is = null;
			try {
				if (zkclient.checkExists().forPath(dpath) == null)
					continue;
				
				byte[] data = getData(dpath);
				is = ManagerInfoStruct.parseFrom(data);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				continue;
			}
			
			int cs = isStatic ? is.getScoresize() : is.getDcoresize();
            if (cs == 0 || is.getMempercent() <= 25) 
                continue;
            
            tcurrpc += isStatic ? is.getScurrentpc() : is.getDcurrentpc();
            
            int of = isStatic ? is.getSoverflowpc() : is.getDoverflowpc();
            if (of > 0) {
                toverflowpc += of;
            } else if (of < 0) {
                ntoverflowpc += of;
            }

            infos.add(is);
		}
		
		ntoverflowpc = -ntoverflowpc;
		for (ManagerInfoStruct info : infos) {
            double tcurrpcscore = 0.0;
            if (tcurrpc != 0)  
                tcurrpcscore = isStatic ? info.getScurrentpc()/tcurrpc : info.getDcurrentpc()/tcurrpc;

            double tsc = 0.2*(info.getMempercent()/100) - 0.6 * tcurrpcscore;
            int of = isStatic ? info.getSoverflowpc() : info.getDoverflowpc();
            if (of > 0)
                tsc -= 0.2*(of/toverflowpc);
            else
                tsc -= 0.2*(of/ntoverflowpc);                                                                                                                                                 

            if (first) {
                first = false;
                score = tsc;
                protocol = info.getProtocol();
            } else if (tsc > score) {
                score = tsc;
                protocol =info.getProtocol();
            }
		}
		return protocol;
	}

}
